# modLogicSignals.py
# Ben Terris 12/1/07
# translation of LogicSignals.java from Steve Varga

from modCalculatable import Calculatable
from modMatrix import Matrix
from modCalculatablePolynomial import CalculatablePolynomial

class LogicSignals(Calculatable):
    '''A Logic Signal class'''
    
    def __init__(self, signal):
        self._mySignal = signal

    def getSignal(self):
        '''Return the logic value of this signal
        >>> print t_sig.getSignal()
        True
        >>> print f_sig.getSignal()
        False
        '''
        
        return self._mySignal

    def __add__(self, rhs):
        '''Perform addition of this logic signal with another object.
            Acts as an OR gate if combined with another logic signal.

        >>> print t_sig + f_sig
        true
        >>> print t_sig + t_sig
        true
        >>> print f_sig + f_sig
        false
        
        '''
        
        if isinstance(rhs, Matrix):
            if self.getSignal():
                #return the same Matrix
                return rhs
            else:
                # return false as false is being applied to the Matrix
                return self
        elif isinstance(rhs, LogicSignals):
            # OR GATE
            return LogicSignals( self.getSignal() or rhs.getSignal() )
        elif isinstance(rhs, CalculatablePolynomial):
            # Apply logic signal to polynomial
            if self.getSignal():
                return rhs
            else:
                return self
        # error if we've reached this point
        return None
    
    def __div__(self, rhs):
        '''Logic Signal division. Acts as an XOR gate when combined with
        another logic signal.

        >>> print t_sig / f_sig
        true
        >>> print t_sig / t_sig
        false
        >>> print f_sig / f_sig
        false
        >>> print f_sig / t_sig
        true
        '''
        
        
        if isinstance(rhs, Matrix):
            # define as invert matrix?
            pass
        elif isinstance(rhs, LogicSignals):
            # XOR GATE
            if (self.getSignal() or rhs.getSignal()):
                if not (self.getSignal() and rhs.getSignal()):
                    return LogicSignals(True)
            return LogicSignals(False)
        elif isinstance(rhs, CalculatablePolynomial):
            if self.getSignal():
                return rhs
            else:
                return self
            
        # error if we've reached this point
        return None
        
    def __mul__(self, rhs):
        '''Perform logic signal multiplication. Acts as an AND gate when
        combined with another logic signal.

        >>> print t_sig * t_sig
        true
        >>> print t_sig * f_sig
        false
        >>> print f_sig * t_sig
        false
        >>> print f_sig * f_sig
        false
        '''
        
        if isinstance(rhs, Matrix):
            return rhs
        elif isinstance(rhs, LogicSignals):
            # AND GATE
            if (self.getSignal() and rhs.getSignal()):
                return LogicSignals(True)
            else:
                return LogicSignals(False)
        elif isinstance(rhs, CalculatablePolynomial):
            if self.getSignal():
                return rhs
            else:
                return self
            
        # error if we've reached this point
        return None

    def __neg__(self):
        '''Logic signal negation.
        >>> print -t_sig
        false
        >>> print -f_sig
        true
        '''
        return LogicSignals( not self.getSignal() )

    def square(self):
        '''Square a logic signal.
        >>> print t_sig.square()
        true
        >>> print f_sig.square()
        false
        '''
        # the square of a logic signal is itself
        return self

    def get(self):
        '''Get a copy of this Logic Signal.'''
        return self

    def __str__(self):
        '''Return a string representation of this signal.
        >>> print t_sig
        true
        >>> print f_sig
        false
        '''
        if self._mySignal == True:
            return "true"
        else:
            return "false"
if __name__ == '__main__':
    # run a battery of unit tests to ensure correct functionality
    t_sig = LogicSignals(True)
    f_sig = LogicSignals(False)
    cPoly = CalculatablePolynomial({3:2.0})


        
    def unittests():
        '''
        '''

    from doctest import testmod
    testmod(verbose=True)


